6. 쿠버네티스 개요5

3.6 서비스 공개

3.6.1 서비스를 사용해서 파드에 접속하기

서비스(Service)란?

쿠버네티스 클러스터에서 실행한 애플리케이션에 네트워크를 통해 접속할 때 필요한 기능이 서비스. 서비스를 사용하면 특정 서비스를 제공하는 여러 파드에 공통 IP 주소를 부여해서 마치 하나의 서비스처럼 접속할 수 있음

서비스가 필요한 이유:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[문제 상황]
    파드 IP는 자주 변경됨
    │
    ├─ 스케일링 시 새 파드 생성 → 새 IP 할당
    ├─ 장애로 파드 재시작 → 새 IP 할당
    └─ 롤링 업데이트 → 새 IP 할당

    클라이언트가 파드 IP를 직접 알기 어려움

[해결책: Service]
    고정 IP + DNS 이름 제공
    │
    ├─ 서비스에 고정 ClusterIP 할당
    ├─ 서비스명으로 DNS 조회 가능
    └─ 로드밸런싱 자동 처리

쿠버네티스는 파드 자체에도 IP 주소가 부여되므로 서비스가 없어도 파드에서 다른 파드에 접근할 수 있음. 하지만 파드의 주소가 자주 바뀔 수 있기 때문에 서비스가 필요함

용어 정리

  • 서비스(Service): 여러 파드를 하나의 고정 IP와 DNS 이름으로 묶어 접근할 수 있게 해주는 쿠버네티스 리소스. 파드 IP가 변경되어도 서비스를 통해 안정적으로 접근 가능
  • ClusterIP: 서비스에 할당되는 클러스터 내부 전용 가상 IP 주소. 외부에서는 접근 불가
  • 로드밸런싱: 트래픽을 여러 파드에 분산하여 부하를 나누는 기능. 서비스가 자동으로 처리함
  • CoreDNS: 쿠버네티스 클러스터의 DNS 서버. 서비스명을 ClusterIP로 변환해줌

서비스의 특징:

서비스 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[클라이언트]
    │
    │ nginx-service:8080 요청
    ↓
[Service: nginx-service]
    ClusterIP: 10.96.100.50
    Port: 8080
    │
    │ selector: app=nginx
    │ 로드밸런싱
    ↓
┌───────────────────────────────┐
│  [Pod1]     [Pod2]     [Pod3] │
│  app:nginx  app:nginx  app:nginx
│  :80        :80        :80    │
└───────────────────────────────┘

서비스의 또 다른 특징으로는 접속할 때 이름을 사용할 수 있다는 것이 있음. 서비스를 작성하면 쿠버네티스 클러스터 내부 DNS와 각 파드의 /etc/resolv.conf에도 설정이 적용되기 때문에, 클러스터 내부라면 서비스에 접속할 때 IP 주소 대신에 서비스명으로 접근할 수 있음


서비스 예제:

파일명: nginx-service.yaml

apiVersion: v1               # Kubernetes 코어 API 버전
kind: Service                # 리소스 타입 - Service (네트워크 추상화)
metadata:
  name: nginx-service        # 서비스 이름 (DNS 이름으로도 사용됨)
spec:
  selector:
    app: nginx               # app=nginx 레이블이 있는 파드를 서비스 대상으로 지정
  ports:
    - protocol: TCP          # 프로토콜 (TCP/UDP)
      port: 8080             # 서비스가 대기하는 포트 (클라이언트가 접속하는 포트)
      targetPort: 80         # 파드가 대기하는 포트 (실제 컨테이너 포트)

파일명: nginx-deployment-3.yaml

apiVersion: apps/v1          # Kubernetes apps API 버전
kind: Deployment             # 리소스 타입 - Deployment
metadata:
  name: nginx-deployment     # 디플로이먼트 이름
spec:
  replicas: 3                # 파드 3개 실행
  selector:
    matchLabels:
      app: nginx             # 관리할 파드 선택 조건
  template:
    metadata:
      labels:
        app: nginx           # 파드에 부여할 레이블 (서비스의 selector와 일치)
    spec:
      containers:
        - name: nginx        # 컨테이너 이름
          image: nginx:1.28  # nginx 이미지 (stable 버전)
          ports:
            - containerPort: 80  # 컨테이너가 노출하는 포트

서비스 배포 및 테스트:

# 디플로이먼트 배포 (파드 3개 생성)
kubectl apply -f nginx-deployment-3.yaml

# 서비스 배포
kubectl apply -f nginx-service.yaml

# 서비스 상태 확인
# CLUSTER-IP: 클러스터 내부에서 접근 가능한 가상 IP
# PORT(S): 서비스포트:타겟포트
kubectl get service nginx-service

# 서비스 상세 정보 확인 (Endpoints에서 연결된 파드 IP 확인 가능)
kubectl describe service nginx-service
# 서비스명으로 접근 테스트
# kubectl run: 임시 파드 생성
# --rm: 명령 완료 후 파드 삭제
# -it: 인터랙티브 터미널 모드
# --restart=Never: 파드를 한 번만 실행
# wget -qO -: 결과를 표준출력으로 출력 (-q: 조용히, -O -: stdout으로)
# nginx-service:8080: 서비스명과 서비스포트로 접근

kubectl run --rm -it svc-client --image=alpine:3.18 --restart=Never -- wget -qO - http://nginx-service:8080

kubectl get service 명령어로 작성 상태를 확인하면 nginx-service 서비스가 작성되었고, 클러스터 내부에서 접속 가능한 IP 주소가 할당된 것을 확인할 수 있음

헤드리스 서비스:

헤드리스 서비스라는 자체 IP 주소나 로드밸런싱 기능이 없는 서비스를 작성할 수도 있음. 헤드리스 서비스는 서비스를 구성하는 각 파드명을 클러스터 내부 DNS에서 각자 해석할 수 있는 기능이 있음 (스테이트풀셋과 함께 사용)

용어 정리

  • 헤드리스 서비스(Headless Service): ClusterIP가 None인 서비스. 로드밸런싱 없이 각 파드에 직접 접근할 수 있으며, StatefulSet과 함께 사용하여 개별 파드를 DNS로 식별
  • Endpoints: 서비스가 트래픽을 전달할 실제 파드 IP 목록. 서비스의 selector와 일치하는 파드들이 자동으로 등록됨


클러스터 내부에서 서비스 접근 테스트

서비스를 생성하면 클러스터 내부에서 다양한 방식으로 접근할 수 있음. 외부에서 접근하기 전에 내부에서 서비스가 제대로 동작하는지 확인하는 것이 중요함

내부 접근 방식:

클러스터 내부 접근 방법:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[방법 1: 서비스명 (DNS)]
    http://nginx-service:8080
    │
    └─ CoreDNS가 서비스명을 ClusterIP로 변환
       가장 권장되는 방식

[방법 2: ClusterIP 직접]
    http://10.96.100.50:8080
    │
    └─ kubectl get service로 확인한 IP 사용
       IP가 변경될 수 있으므로 테스트용

[방법 3: 전체 DNS 이름]
    http://nginx-service.default.svc.cluster.local:8080
    │
    └─ 다른 네임스페이스에서 접근 시 사용
       <서비스명>.<네임스페이스>.svc.cluster.local

내부 접근 테스트 방법:

# 방법 1: 임시 파드에서 테스트 (권장)
kubectl run test-client --rm -it --image=curlimages/curl --restart=Never -- http://nginx-service:8080

# 방법 2: 기존 파드에서 테스트
kubectl exec -it <pod-name> -- curl http://nginx-service:8080

# 방법 3: ClusterIP로 직접 테스트
kubectl exec -it <pod-name> -- curl http://10.96.100.50:8080

# 방법 4: busybox로 테스트
kubectl run test --rm -it --image=busybox --restart=Never -- wget -qO- http://nginx-service:8080

DNS 확인:

# 서비스 DNS 조회
kubectl run dns-test --rm -it --image=busybox --restart=Never -- nslookup nginx-service

# 출력 예시:
# Server:    10.96.0.10
# Address:   10.96.0.10:53
# Name:      nginx-service.default.svc.cluster.local
# Address:   10.96.100.50

3.6.2 외부에 서비스 공개하기

서비스 기능을 사용해서 어떤 서비스를 구성하는 파드 그룹을 하나로 묶어서 공통 IP 주소를 부여할 수 있지만, 이렇게 작성한 서비스는 클러스터 IP(ClusterIP)이기 때문에 서비스에 부여된 IP 주소는 쿠버네티스 내부에서만 유효하고 인터넷 같은 클러스터 외부에서는 접근할 수 없음

서비스 타입 계층 구조:

서비스 타입은 상위 타입이 하위 타입의 기능을 모두 포함하는 계층 구조를 가짐

서비스 타입 상속 관계:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ClusterIP (기본)
    │
    └─ 내부 접근만 가능
       - ClusterIP: 10.96.100.50
       - DNS: nginx-service

        ↓ 상속

NodePort = ClusterIP + 노드포트
    │
    ├─ ClusterIP 기능 포함 (내부 접근)
    │  - ClusterIP: 10.96.100.50
    │  - DNS: nginx-service
    │
    └─ + 노드포트 추가 (외부 접근)
       - <모든노드IP>:30080

        ↓ 상속

LoadBalancer = NodePort + 외부 LB
    │
    ├─ ClusterIP 기능 포함
    ├─ NodePort 기능 포함
    └─ + 클라우드 로드밸런서 추가
       - External IP: 203.0.113.10

하나의 NodePort 서비스에 대한 접근 방식:

예: nginx-nodeport 서비스 (TYPE: NodePort)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

kubectl get service nginx-nodeport
→ CLUSTER-IP: 10.102.184.141, PORT: 80:30080/TCP

[클러스터 내부에서 접근 (3가지 모두 가능)]
    │
    ├─ nginx-nodeport:80      (DNS → ClusterIP)
    ├─ 10.102.184.141:80      (ClusterIP 직접)
    └─ 192.168.65.3:30080     (노드IP + NodePort)

[클러스터 외부에서 접근]
    │
    ├─ localhost:30080        (Docker Desktop 자동 포워딩)
    └─ <공인IP>:30080         (실제 노드의 공인IP)

[접근 불가]
    │
    ├─ Windows → 192.168.65.3:30080  ✗ (VM 내부 IP)
    └─ Windows → 10.102.184.141:80   ✗ (클러스터 내부 IP)

외부 트래픽 흐름 (NodePort 예시):

외부에서 NodePort로 접근 시 트래픽 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[외부 클라이언트]
    │
    │ http://<공인IP>:30080
    ↓
[Node (공인IP:30080)]
    │
    │ NodePort가 트래픽 수신
    ↓
[kube-proxy]
    │
    │ iptables/IPVS 규칙으로 라우팅
    ↓
[Service (ClusterIP:80)]
    │
    │ 로드밸런싱 (라운드로빈)
    ↓
[Pod 선택]
    ├─ Pod1:80
    ├─ Pod2:80
    └─ Pod3:80

서비스 타입별 포트 관계:

포트 용어 정리:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[NodePort 서비스 예시]
spec:
  type: NodePort
  ports:
    - port: 80           # 서비스 포트 (ClusterIP에서 사용)
      targetPort: 80     # 파드 포트 (컨테이너가 리스닝)
      nodePort: 30080    # 노드 포트 (외부 노출)

접근 경로:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

외부 → <노드IP>:30080 (nodePort)
          ↓
내부 → ClusterIP:80 (port)
          ↓
파드 → Pod:80 (targetPort)
서비스 타입 비교:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[ClusterIP] (기본값)
    ├─ 클러스터 내부에서만 접근 가능
    └─ 외부 노출 불가

[NodePort]
    ├─ 각 노드의 고정 포트로 외부 노출
    ├─ 포트 범위: 30000-32767
    └─ 노드 IP:포트로 접근

[LoadBalancer]
    ├─ 외부 로드밸런서 자동 프로비저닝
    ├─ 클라우드 환경에서 주로 사용
    └─ 로컬 환경에서는 (Bare)MetalLB 필요

[ExternalName]
    ├─ 외부 DNS 이름을 서비스로 매핑
    └─ 클러스터 외부 서비스 참조용
용어 정리

  • NodePort: 각 노드의 고정 포트(30000-32767)를 통해 외부에서 접근할 수 있게 하는 서비스 타입. ClusterIP 기능을 포함함
  • LoadBalancer: 클라우드 로드밸런서를 자동 프로비저닝하여 외부 IP를 할당받는 서비스 타입. NodePort와 ClusterIP 기능을 포함함
  • ExternalName: 외부 도메인을 클러스터 내부 서비스명으로 참조할 수 있게 해주는 서비스 타입
  • kube-proxy: 각 노드에서 서비스 트래픽을 적절한 파드로 라우팅하는 컴포넌트. iptables 또는 IPVS 규칙을 관리함
  • targetPort: 파드 내 컨테이너가 실제로 리스닝하는 포트
  • port: 서비스가 클러스터 내부에서 노출하는 포트 (ClusterIP에서 사용)
  • nodePort: 노드 외부에서 접근 시 사용하는 포트 (30000-32767 범위)

외부 접근 방식 다이어그램:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[인터넷/외부 클라이언트]
        │
        ↓
┌─────────────────────────────────────┐
│           [LoadBalancer]            │
│         외부 IP: 203.0.113.10       │
│               :80                   │
│                 │                   │
│  ┌──────────────┼──────────────┐    │
│  │              ↓              │    │
│  │     [NodePort Service]      │    │
│  │    모든 노드의 :30080        │    │
│  │              │              │    │
│  ├──────────────┼──────────────┤    │
│  │              ↓              │    │
│  │    [ClusterIP Service]      │    │
│  │      10.96.100.50:80        │    │
│  │              │              │    │
│  │    ┌─────────┼─────────┐    │    │
│  │    ↓         ↓         ↓    │    │
│  │  [Pod1]   [Pod2]   [Pod3]   │    │
│  │   :80      :80      :80     │    │
│  └─────────────────────────────┘    │
│          Kubernetes Cluster         │
└─────────────────────────────────────┘

NodePort 서비스:

NodePort는 서비스의 일종으로, 각 노드의 고정 포트를 클러스터 외부에 공개해서 해당 포트를 통한 통신을, 서비스를 구성하는 파드 중 하나에 로드밸런싱함

NodePort 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[외부 클라이언트]
    │
    │ http://<노드IP>:30080
    ↓
┌─────────────────────────────────────┐
│  [Node1:30080] [Node2:30080] [Node3:30080]
│       │             │             │
│       └─────────────┼─────────────┘
│                     ↓
│            [Service: NodePort]
│                     │
│       ┌─────────────┼─────────────┐
│       ↓             ↓             ↓
│    [Pod1]        [Pod2]        [Pod3]
│     :80           :80           :80
└─────────────────────────────────────┘

특징:
├─ 어느 노드의 30080 포트로 접근해도 동일 서비스
├─ 포트 범위: 30000-32767
└─ 노드 IP를 직접 알아야 함

파일명: nodeport-service.yaml

apiVersion: v1               # Kubernetes 코어 API 버전
kind: Service                # 리소스 타입 - Service
metadata:
  name: nginx-nodeport       # 서비스 이름
spec:
  type: NodePort             # 서비스 타입 - NodePort (외부 노출)
  selector:
    app: nginx               # app=nginx 레이블이 있는 파드 대상
  ports:
    - protocol: TCP          # 프로토콜
      port: 80               # 클러스터 내부에서 서비스 접근 시 사용하는 포트
      targetPort: 80         # 파드가 대기하는 포트
      nodePort: 30080        # 노드에서 외부로 노출하는 포트 (30000-32767 범위)
                             # 생략 시 자동 할당

NodePort 배포 및 테스트:

# NodePort 서비스 배포
kubectl apply -f nodeport-service.yaml

# 서비스 확인
# TYPE: NodePort
# PORT(S): 80:30080/TCP (서비스포트:노드포트)
kubectl get service nginx-nodeport

# 노드 IP 확인
kubectl get nodes -o wide

# 외부에서 접근 테스트 (노드IP:노드포트)
# Windows에서는 localhost 또는 Docker Desktop의 IP 사용
curl http://localhost:30080
# 또는
curl http://<노드-IP>:30080

단, 노드 자체에서 클러스터 외부 공개가 여러 개이거나 또는 노드가 여러 개라면 노드 그룹의 로드밸런서 설정은 사용자가 직접 해야 함


LoadBalancer 서비스:

로드밸런서 서비스도 서비스의 일종. 클라우드 제공 업체처럼 쿠버네티스용 로드밸런서 기능을 제공하는 플랫폼에서 사용할 수 있으며, 로드밸런서를 통해 각 서비스를 클러스터 외부에 공개할 수 있음

LoadBalancer 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[외부 클라이언트]
    │
    │ http://203.0.113.10:80
    ↓
[Cloud Load Balancer]         ← 클라우드가 자동 프로비저닝
    External IP: 203.0.113.10
    │
    │ 트래픽 분산
    ↓
┌─────────────────────────────────────┐
│  [Node1]     [Node2]     [Node3]    │
│     │           │           │       │
│     └───────────┼───────────┘       │
│                 ↓                   │
│        [Service: LoadBalancer]      │
│                 │                   │
│       ┌─────────┼─────────┐         │
│       ↓         ↓         ↓         │
│    [Pod1]    [Pod2]    [Pod3]       │
└─────────────────────────────────────┘

파일명: loadbalancer-service.yaml

apiVersion: v1               # Kubernetes 코어 API 버전
kind: Service                # 리소스 타입 - Service
metadata:
  name: nginx-loadbalancer   # 서비스 이름
spec:
  type: LoadBalancer         # 서비스 타입 - LoadBalancer (외부 LB 사용)
  selector:
    app: nginx               # app=nginx 레이블이 있는 파드 대상
  ports:
    - protocol: TCP          # 프로토콜
      port: 80               # 외부 로드밸런서가 대기하는 포트
      targetPort: 80         # 파드가 대기하는 포트

LoadBalancer 배포:

# LoadBalancer 서비스 배포
kubectl apply -f loadbalancer-service.yaml

# 서비스 확인
# EXTERNAL-IP: 외부에서 접근 가능한 IP (할당 시간 소요)
# 클라우드 환경에서는 실제 공인 IP 할당
# 로컬 환경에서는 <pending> 상태 유지 (MetalLB 없는 경우)
kubectl get service nginx-loadbalancer

# 외부 IP 할당 대기 (실시간 확인)
kubectl get service nginx-loadbalancer -w

클러스터 외부에서 보면 로드밸런서가 공개한 IP 주소와 포트에 접속하면 해당 포트를 공개하는 로드밸런서 서비스를 통해서 서비스를 구성하는 파드 중 하나에 통신이 전송됨. GKE, EKS, AKS 등의 플랫폼이 제공하는 로드밸런서 기능을 사용하는 것임

로컬 환경에서 LoadBalancer 사용하기 (MetalLB):

클라우드가 아닌 로컬 환경(Docker Desktop, Minikube, 베어메탈)에서는 LoadBalancer 타입을 사용해도 EXTERNAL-IP가 <pending> 상태로 유지됨. 이때 MetalLB를 설치하면 로컬에서도 LoadBalancer를 사용할 수 있음

# MetalLB 설치 (네임스페이스 및 컴포넌트)
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml

# MetalLB 파드 준비 대기
kubectl wait --namespace metallb-system --for=condition=ready pod --selector=app=metallb --timeout=90s

MetalLB IP 풀 설정 파일: metallb-config.yaml

apiVersion: metallb.io/v1beta1   # MetalLB API 버전
kind: IPAddressPool              # IP 주소 풀 정의
metadata:
  name: default-pool             # 풀 이름
  namespace: metallb-system      # MetalLB 네임스페이스
spec:
  addresses:
    - 192.168.49.100-192.168.49.120  # 할당할 IP 범위 (환경에 맞게 수정)
                                      # Docker Desktop: 172.17.0.100-172.17.0.120
                                      # Minikube: minikube ip 결과 참고

---

apiVersion: metallb.io/v1beta1   # MetalLB API 버전
kind: L2Advertisement            # L2 모드 광고 설정
metadata:
  name: default                  # 광고 이름
  namespace: metallb-system      # MetalLB 네임스페이스
# MetalLB 설정 적용
kubectl apply -f metallb-config.yaml

# 이제 LoadBalancer 서비스에 EXTERNAL-IP 할당됨
kubectl get service nginx-loadbalancer

인그레스 (Ingress):

인그레스는 다수의 서비스 접속을 관리할 수 있는 기능. 예를 들어 하나의 HTTP 기반 애플리케이션을 여러 개의 서비스를 사용해 구성하고, URL 호스트명과 경로 규칙을 기반으로 실제로 접속할 서비스를 매니페스트에 지정할 수 있는 등 로드밸런싱 기능이 포함되어 있음

인그레스 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[외부 요청]
    │
    ├─ http://example.com/api/*
    ├─ http://example.com/web/*
    └─ http://admin.example.com/*
    │
    ↓
[Ingress Controller]          ← nginx-ingress, traefik 등
    │
    │ URL 경로/호스트 기반 라우팅
    │
    ├─ /api/*     → [Service: api-service]     → [API Pods]
    ├─ /web/*     → [Service: web-service]     → [Web Pods]
    └─ admin.*    → [Service: admin-service]   → [Admin Pods]

장점:
├─ 하나의 외부 IP로 여러 서비스 노출
├─ URL 경로 기반 라우팅
├─ 호스트명 기반 라우팅
├─ SSL/TLS 종료 처리
└─ 로드밸런서 비용 절감

쿠버네티스 자체는 인그레스를 관리하는 컴포넌트가 포함되지 않으므로 사용자가 직접 도입하거나 클라우드 제공 업체의 쿠버네티스 운영 플랫폼에서 제공하는 것을 사용해야 함

용어 정리

  • 인그레스(Ingress): HTTP/HTTPS 트래픽을 URL 경로나 호스트명 기반으로 여러 서비스로 라우팅하는 API 객체. L7 로드밸런싱 제공
  • 인그레스 컨트롤러(Ingress Controller): 인그레스 리소스를 실제로 처리하는 컴포넌트. nginx-ingress, traefik 등 다양한 구현체가 있음
  • ingressClassName: 어떤 인그레스 컨트롤러가 해당 인그레스를 처리할지 지정하는 필드
  • pathType: URL 경로 매칭 방식. Prefix(접두사 매칭), Exact(정확히 일치), ImplementationSpecific(컨트롤러 구현에 따름)
  • SSL/TLS 종료(Termination): HTTPS 암호화를 인그레스 컨트롤러에서 해제하여 내부 서비스에는 HTTP로 전달하는 것
  • MetalLB: 베어메탈/로컬 환경에서 LoadBalancer 서비스를 사용할 수 있게 해주는 로드밸런서 구현체

인그레스 컨트롤러는 다양한 구현체가 있음:

Ingress-NGINX 설치 (로컬/베어메탈 환경):

# Ingress-NGINX 컨트롤러 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/cloud/deploy.yaml

# 설치 확인
kubectl get pods -n ingress-nginx

# Ingress 컨트롤러 서비스 확인
kubectl get service -n ingress-nginx

인그레스 예제:

파일명: ingress-example.yaml

#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 서비스 정의
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

apiVersion: v1               # Kubernetes 코어 API 버전
kind: Service                # 리소스 타입 - Service
metadata:
  name: nginx-service        # 서비스 이름
spec:
  selector:
    app: nginx               # app=nginx 레이블이 있는 파드 대상
  ports:
    - protocol: TCP          # 프로토콜
      port: 80               # 서비스 포트
      targetPort: 80         # 파드 포트

---

#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 인그레스 정의
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

apiVersion: networking.k8s.io/v1  # Ingress API 버전 (networking.k8s.io/v1 권장)
kind: Ingress                     # 리소스 타입 - Ingress
metadata:
  name: nginx-ingress             # 인그레스 이름
  annotations:                    # 인그레스 컨트롤러별 설정
    nginx.ingress.kubernetes.io/rewrite-target: /  # URL 재작성 (선택사항)
spec:
  ingressClassName: nginx         # 사용할 인그레스 컨트롤러 클래스
                                  # Ingress-NGINX 사용 시 "nginx"
  rules:
    - host: example.local         # 호스트명 (생략 시 모든 호스트에 적용)
      http:
        paths:
          - path: /               # URL 경로 (루트 경로)
            pathType: Prefix      # 경로 매칭 방식
                                  # Prefix: /로 시작하는 모든 경로
                                  # Exact: 정확히 일치하는 경로만
                                  # ImplementationSpecific: 컨트롤러 구현에 따름
            backend:
              service:
                name: nginx-service  # 트래픽을 전달할 서비스 이름
                port:
                  number: 80         # 서비스 포트

인그레스 배포 및 테스트:

# 디플로이먼트와 인그레스 배포
kubectl apply -f nginx-deployment-3.yaml
kubectl apply -f ingress-example.yaml

# 인그레스 상태 확인
# ADDRESS: 인그레스 컨트롤러의 외부 IP
kubectl get ingress nginx-ingress

# 인그레스 상세 정보
kubectl describe ingress nginx-ingress

# 로컬 테스트 (hosts 파일 수정 또는 Host 헤더 사용)
# Linux/macOS
curl -H "Host: example.local" http://localhost

# Windows PowerShell
curl.exe -H "Host: example.local" http://localhost
# 또는 Invoke-WebRequest
Invoke-WebRequest -Uri "http://localhost" -Headers @{"Host"="example.local"}

다중 경로 인그레스 예제:

파일명: multi-path-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-path-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2  # 캡처 그룹으로 경로 재작성
spec:
  ingressClassName: nginx
  rules:
    - host: myapp.local
      http:
        paths:
          # /api/* 요청은 api-service로 라우팅
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: api-service
                port:
                  number: 8080

          # /web/* 요청은 web-service로 라우팅
          - path: /web(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: web-service
                port:
                  number: 80

          # 기본 경로는 default-service로 라우팅
          - path: /
            pathType: Prefix
            backend:
              service:
                name: default-service
                port:
                  number: 80

서비스 타입 선택 가이드:

서비스 타입 선택 기준:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[ClusterIP]
    사용 시점:
    ├─ 클러스터 내부 통신만 필요
    ├─ 마이크로서비스 간 통신
    └─ 외부 노출 불필요

[NodePort]
    사용 시점:
    ├─ 개발/테스트 환경
    ├─ 간단한 외부 노출 필요
    └─ 로드밸런서 없는 환경

    제한:
    ├─ 포트 범위 제한 (30000-32767)
    └─ 노드 IP 직접 노출

[LoadBalancer]
    사용 시점:
    ├─ 프로덕션 환경
    ├─ 클라우드 환경 (GKE, EKS, AKS)
    └─ 고가용성 필요

    로컬 환경:
    └─ MetalLB 설치 필요

[Ingress]
    사용 시점:
    ├─ 여러 서비스를 하나의 IP로 노출
    ├─ URL 경로 기반 라우팅 필요
    ├─ SSL/TLS 종료 처리
    └─ 로드밸런서 비용 절감

    필수 조건:
    └─ Ingress Controller 설치 필요

리소스 정리:

# 서비스 삭제
kubectl delete service nginx-service nginx-nodeport nginx-loadbalancer

# 인그레스 삭제
kubectl delete ingress nginx-ingress

# 디플로이먼트 삭제
kubectl delete deployment nginx-deployment

# 또는 파일로 삭제
kubectl delete -f nginx-service.yaml
kubectl delete -f nodeport-service.yaml
kubectl delete -f loadbalancer-service.yaml
kubectl delete -f ingress-example.yaml

참고 자료

공식 문서:

Ingress Controller: